home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / UNIX.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  42KB  |  1,781 lines

  1. /***
  2.     UNIX driver/Microemacs 3.10b/3.10k,
  3.     Copyright 1989/1993 D. Lawrence, C. Smith
  4.  ***/
  5.  
  6. /**
  7.     New features:
  8.  
  9.     1. Timeouts waiting on a function key have been changed from
  10.     35000 to 500000 microseconds.
  11.  
  12.     2. Additional keymapping entries can be made from the command
  13.     language by issuing a 'set $palette xxx'.  The format of
  14.     xxx is a string as follows:
  15.         "KEYMAP keybinding escape-sequence".
  16.     To add "<ESC><[><A>" as a keybinding of FNN, issue:
  17.         "KEYMAP FNN ^[[A".
  18.     Note that the escape character!  It is a real escape character
  19.     and it's pretty difficult to enter.
  20.  
  21.     3. Colors are supported.  Under AIX the colors will be pulled
  22.     in automaticly.  For other environments, you can either add
  23.     the termcap entries, C0 to D7.  Or the colors may be defined
  24.     using the command language by issuing a 'set $palette xxx'
  25.     command.  The format of xxx is a string as follows:
  26.         "CLRMAP # escape-sequence".
  27.     The number is a number from 0 to 15, where 0 to 7 is the
  28.     foreground colors, and 8 to 15 as background colors.
  29.     To add foreground color 0 for ansi terminals, issue:
  30.         "CLRMAP 0 ^[[30m".
  31.     
  32.     'Porting notes:
  33.  
  34.     I have tried to create this file so that it should work
  35.     as well as possible without changes on your part.
  36.  
  37.     However, if something does go wrong, read the following
  38.     helpful hints:
  39.  
  40.     1. On SUN-OS4, there is a problem trying to include both
  41.     the termio.h and ioctl.h files.  I wish Sun would get their
  42.     act together.  Even though you get lots of redefined messages,
  43.     it shouldn't cause any problems with the final object.
  44.  
  45.     2. In the type-ahead detection code, the individual UNIX
  46.     system either has a FIONREAD or a FIORDCHK ioctl call.
  47.     Hopefully, your system uses one of them and this be detected
  48.     correctly without any intervention.
  49.  
  50.     3. Also lookout for directory handling.  The SCO Xenix system
  51.     is the weirdest I've seen, requiring a special load file
  52.     (see below).  Some machine call the result of a readdir() call
  53.     a "struct direct" or "struct dirent".  Includes files are
  54.     named differently depending of the O/S.  If your system doesn't
  55.     have an opendir()/closedir()/readdir() library call, then
  56.     you should use the public domain utility "ndir".
  57.  
  58.     To compile:
  59.         Compile all files normally.
  60.     To link:
  61.         Select one of the following operating systems:
  62.             SCO Xenix:
  63.                 use "-ltermcap" and "-lx";
  64.             SUN 3 and 4:
  65.                 use "-ltermcap";
  66.             IBM-RT, IBM-AIX, ATT UNIX, Altos UNIX, Interactive:
  67.                 use "-lcurses".
  68. **/
  69.  
  70. /** Include files **/
  71. #include <stdio.h>            /* Standard I/O definitions    */
  72. #include "estruct.h"            /* Emacs definitions        */
  73.  
  74. /** Do nothing routine **/
  75. int scnothing()
  76. {
  77.     return(0);
  78. }
  79.  
  80. /** Only compile for UNIX machines **/
  81. #if BSD || USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || AVIION
  82.  
  83. /** Include files **/
  84. #include "eproto.h"            /* Function definitions        */
  85. #include "edef.h"            /* Global variable definitions    */
  86. #include "elang.h"            /* Language definitions        */
  87.  
  88. /** Kill predefined **/
  89. #undef CTRL                /* Problems with CTRL        */
  90.  
  91. /** Overall include files **/
  92. #include <sys/types.h>            /* System type definitions    */
  93. #include <sys/stat.h>            /* File status definitions    */
  94. #include <sys/ioctl.h>            /* I/O control definitions    */
  95.  
  96. /** Additional include files **/
  97. #if BSD
  98. #include <sys/time.h>            /* Timer definitions        */
  99. #endif /* BSD */
  100. #if BSD || SUN || HPUX8 || HPUX9 || AVIION
  101. #include <signal.h>            /* Signal definitions        */
  102. #endif /* BSD || SUN || HPUX8 || HPUX9 || AVIION */
  103. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  104. #include <termio.h>            /* Terminal I/O definitions    */
  105. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  106. #if AVIION
  107. #include <termios.h>            /* Terminal I/O definitions    */
  108. #endif /* AVIION */
  109. #if CURSES
  110. #include <curses.h>            /* Curses screen output        */
  111. #undef WINDOW                /* Oh no!            */
  112. #endif /* CURSES */
  113.  
  114. /** Completion include files **/
  115. /** Directory accessing: Try and figure this out... if you can! **/
  116. #if BSD
  117. #include <sys/dir.h>            /* Directory entry definitions    */
  118. #define DIRENTRY    direct
  119. #endif /* BSD */
  120. #if XENIX || VAT
  121. #include <sys/ndir.h>            /* Directory entry definitions    */
  122. #define DIRENTRY    direct
  123. #endif /* XENIX */
  124. #if ((USG || AUX) && !VAT) || SMOS || HPUX8 || HPUX9 || SUN || AVIION
  125. #include <dirent.h>            /* Directory entry definitions    */
  126. #define DIRENTRY    dirent
  127. #endif /* ((USG || AUX) && !VAT) || SMOS || HPUX8 || HPUX9 || SUN || AVIION */
  128.  
  129. /** Restore predefined definitions **/
  130. #undef CTRL                /* Restore CTRL            */
  131. #define CTRL 0x0100
  132.  
  133. /** Parameters **/
  134. #define NKEYENT        300        /* Number of keymap entries    */
  135. #define NINCHAR        64        /* Input buffer size        */
  136. #define NOUTCHAR    256        /* Output buffer size        */
  137. #if TERMCAP
  138. #define NCAPBUF        1024        /* Termcap storage size        */
  139. #endif /* TERMCAP */
  140. #define MARGIN        8        /* Margin size            */
  141. #define SCRSIZ        64        /* Scroll for margin        */
  142. #define NPAUSE        10        /* # times thru update to pause */
  143.  
  144. /** CONSTANTS **/
  145. #define TIMEOUT        255        /* No character available    */
  146.  
  147. /** Type definitions **/
  148. struct keyent {                /* Key mapping entry        */
  149.     struct keyent * samlvl;        /* Character on same level    */
  150.     struct keyent * nxtlvl;        /* Character on next level    */
  151.     unsigned char ch;        /* Character            */
  152.     int code;            /* Resulting keycode        */
  153. };
  154. #if TERMCAP
  155. struct capbind {            /* Capability binding entry    */
  156.     char * name;            /* Termcap name            */
  157.     char * store;            /* Storage variable        */
  158. };
  159. struct keybind {            /* Keybinding entry        */
  160.     char * name;            /* Termcap name            */
  161.     int value;            /* Binding value        */
  162. };
  163. char *reset = (char*) NULL;        /* reset string kjc */
  164. #endif /* TERMCAP */
  165.  
  166. /** Local variables **/
  167. #if BSD
  168. static struct sgttyb cursgtty;        /* Current modes        */
  169. static struct sgttyb oldsgtty;        /* Original modes        */
  170. static struct tchars oldtchars;        /* Current tchars        */
  171. static struct ltchars oldlchars;    /* Current ltchars        */
  172. static char blank[6] =            /* Blank out character set    */
  173.     { -1, -1, -1, -1, -1, -1 };
  174. #endif /* BSD */
  175. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  176. static struct termio curterm;        /* Current modes        */
  177. static struct termio oldterm;        /* Original modes        */
  178. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  179. #if AVIION
  180. static struct termios curterm;        /* Current modes        */
  181. static struct termios oldterm;        /* Original modes        */
  182. #endif /* AVIION */
  183. #if TERMCAP
  184. static char tcapbuf[NCAPBUF];        /* Termcap character storage    */
  185. #define CAP_CL        0        /* Clear to end of page        */
  186. #define CAP_CM        1        /* Cursor motion        */
  187. #define CAP_CE        2        /* Clear to end of line        */
  188. #define CAP_SE        3        /* Standout ends        */
  189. #define CAP_SO        4        /* Standout (reverse video)    */
  190. #define CAP_IS        5        /* Initialize screen        */
  191. #define CAP_KS        6        /* Keypad mode starts        */
  192. #define CAP_KE        7        /* Keypad mode ends        */
  193. #define CAP_VB        8        /* Visible bell            */
  194. #if COLOR
  195. #define CAP_C0        9        /* Foreground color #0        */
  196. #define CAP_C1        10        /* Foreground color #1        */
  197. #define CAP_C2        11        /* Foreground color #2        */
  198. #define CAP_C3        12        /* Foreground color #3        */
  199. #define CAP_C4        13        /* Foreground color #4        */
  200. #define CAP_C5        14        /* Foreground color #5        */
  201. #define CAP_C6        15        /* Foreground color #6        */
  202. #define CAP_C7        16        /* Foreground color #7        */
  203. #define CAP_D0        17        /* Background color #0        */
  204. #define CAP_D1        18        /* Background color #1        */
  205. #define CAP_D2        19        /* Background color #2        */
  206. #define CAP_D3        20        /* Background color #3        */
  207. #define CAP_D4        21        /* Background color #4        */
  208. #define CAP_D5        22        /* Background color #5        */
  209. #define CAP_D6        23        /* Background color #6        */
  210. #define CAP_D7        24        /* Background color #7        */
  211. #if USG || AUX
  212. #define CAP_SF        25        /* Set foreground color        */
  213. #define CAP_SB        26        /* Set background color        */
  214. #endif /* USG || AUX */
  215. #endif /* COLOR */
  216. static struct capbind capbind[] = {    /* Capability binding list    */
  217.     { "cl" },            /* Clear to end of page        */
  218.     { "cm" },            /* Cursor motion        */
  219.     { "ce" },            /* Clear to end of line        */
  220.     { "se" },            /* Standout ends        */
  221.     { "so" },            /* Standout (reverse video)    */
  222.     { "is" },            /* Initialize screen        */
  223.     { "ks" },            /* Keypad mode starts        */
  224.     { "ke" },            /* Keypad mode ends        */
  225.     { "vb" },            /* Visible bell            */
  226. #if COLOR
  227.     { "c0" },            /* Foreground color #0        */
  228.     { "c1" },            /* Foreground color #1        */
  229.     { "c2" },            /* Foreground color #2        */
  230.     { "c3" },            /* Foreground color #3        */
  231.     { "c4" },            /* Foreground color #4        */
  232.     { "c5" },            /* Foreground color #5        */
  233.     { "c6" },            /* Foreground color #6        */
  234.     { "c7" },            /* Foreground color #7        */
  235.     { "d0" },            /* Background color #0        */
  236.     { "d1" },            /* Background color #1        */
  237.     { "d2" },            /* Background color #2        */
  238.     { "d3" },            /* Background color #3        */
  239.     { "d4" },            /* Background color #4        */
  240.     { "d5" },            /* Background color #5        */
  241.     { "d6" },            /* Background color #6        */
  242.     { "d7" },            /* Background color #7        */
  243. #if USG || AUX
  244.     { "Sf" },            /* Set foreground color        */
  245.     { "Sb" },            /* Set background color        */
  246. #endif /* USG || AUX */
  247. #endif /* COLOR */
  248. };
  249. #if COLOR
  250. static int cfcolor = -1;        /* Current forground color    */
  251. static int cbcolor = -1;        /* Current background color    */
  252. #endif /* COLOR */
  253. static struct keybind keybind[] = {    /* Keybinding list        */
  254.     { "bt", SHFT|CTRL|'i' },    /* Back-tab key            */
  255.     { "k1", SPEC|'1' },        /* F1 key            */
  256.     { "k2", SPEC|'2' },        /* F2 key            */
  257.     { "k3", SPEC|'3' },        /* F3 key            */
  258.     { "k4", SPEC|'4' },        /* F4 key            */
  259.     { "k5", SPEC|'5' },        /* F5 key            */
  260.     { "k6", SPEC|'6' },        /* F6 key            */
  261.     { "k7", SPEC|'7' },        /* F7 key            */
  262.     { "k8", SPEC|'8' },        /* F8 key            */
  263.     { "k9", SPEC|'9' },        /* F9 key            */
  264.     { "k0", SPEC|'0' },        /* F0 or F10 key        */
  265.      { "k;", SPEC|'0' },        /* F0 or F10 key    (kjc)    */
  266.     { "F1", SHFT|SPEC|'1' },    /* Shift-F1 or F11 key        */
  267.     { "F2", SHFT|SPEC|'2' },    /* Shift-F2 or F12 key        */
  268.     { "F3", SHFT|SPEC|'3' },    /* Shift-F3 or F13 key        */
  269.     { "F4", SHFT|SPEC|'4' },    /* Shift-F4 or F14 key        */
  270.     { "F5", SHFT|SPEC|'5' },    /* Shift-F5 or F15 key        */
  271.     { "F6", SHFT|SPEC|'6' },    /* Shift-F6 or F16 key        */
  272.     { "F7", SHFT|SPEC|'7' },    /* Shift-F7 or F17 key        */
  273.     { "F8", SHFT|SPEC|'8' },    /* Shift-F8 or F18 key        */
  274.     { "F9", SHFT|SPEC|'9' },    /* Shift-F9 or F19 key        */
  275.     { "FA", SHFT|SPEC|'0' },    /* Shift-F0 or F20 key        */
  276.     { "kA", CTRL|'O' },        /* Insert line key        */
  277.     { "kb", CTRL|'H' },        /* Backspace key        */
  278.     { "kC", CTRL|'L' },        /* Clear screen key        */
  279.     { "kD", SPEC|'D' },        /* Delete character key        */
  280.     { "kd", SPEC|'N' },        /* Down arrow key        */
  281.     { "kE", CTRL|'K' },        /* Clear to end of line key    */
  282.     { "kF", CTRL|'V' },        /* Scroll forward key        */
  283.     { "kH", SPEC|'>' },        /* Home down key        */
  284.      { "@7", SPEC|'>' },        /* Home down key    (kjc)    */
  285.     { "kh", SPEC|'<' },        /* Home key            */
  286.     { "kI", SPEC|'C' },        /* Insert character key        */
  287.     { "kL", CTRL|'K' },        /* Delete line key        */
  288.     { "kl", SPEC|'B' },        /* Left arrow key        */
  289.     { "kN", SPEC|'V' },        /* Next page key        */
  290.     { "kP", SPEC|'Z' },        /* Previous page key        */
  291.     { "kR", CTRL|'Z' },        /* Scroll backward key        */
  292.     { "kr", SPEC|'F' },        /* Right arrow key        */
  293.     { "ku", SPEC|'P' }        /* Up arrow key            */
  294. };
  295. #endif /* TERMCAP */
  296. static int inbuf[NINCHAR];        /* Input buffer            */
  297. static int * inbufh =            /* Head of input buffer        */
  298.     inbuf;
  299. static int * inbuft =            /* Tail of input buffer        */
  300.     inbuf;
  301. #if TERMCAP
  302. static unsigned char outbuf[NOUTCHAR];    /* Output buffer        */
  303. static unsigned char * outbuft =     /* Output buffer tail        */
  304.     outbuf;
  305. #endif /* TERMCAP */
  306. static unsigned char keyseq[256];    /* Prefix escape sequence table    */
  307. static struct keyent keymap[NKEYENT];    /* Key map            */
  308. static struct keyent * nxtkey =        /* Next free key entry        */
  309.     keymap;
  310. static DIR *dirptr = NULL;        /* Current directory stream    */
  311. static char path[NFILEN];        /* Path of file to find        */
  312. static char rbuf[NFILEN];        /* Return file buffer        */
  313. static char *nameptr;            /* Ptr past end of path in rbuf    */
  314.  
  315. /** Terminal definition block **/
  316. int scopen(), scclose(), ttgetc(), ttputc(), ttflush();
  317. int scmove(), sceeol(), sceeop(), scbeep(), screv();
  318. int sckopen(), sckclose();
  319. #if COLOR
  320. int scfcol(), scbcol();
  321. #endif /* COLOR */
  322.  
  323. #if    TERMCAP && FLABEL
  324. static void dis_sfk(), dis_ufk();
  325. #endif
  326.  
  327. TERM term = {
  328.     120,                /* Maximum number of rows    */
  329.     0,                /* Current number of rows    */
  330.     132,                /* Maximum number of columns    */
  331.     0,                /* Current number of columns    */
  332.     0, 0,                /* upper left corner default screen */
  333.     MARGIN,                /* Margin for extending lines    */
  334.     SCRSIZ,                /* Scroll size for extending    */
  335.     NPAUSE,                /* # times thru update to pause    */
  336.     scopen,                /* Open terminal routine    */
  337.     scclose,            /* Close terminal routine    */
  338.     sckopen,            /* Open keyboard routine    */
  339.     sckclose,            /* Close keyboard routine    */
  340.     ttgetc,                /* Get character routine    */
  341.     ttputc,                /* Put character routine    */
  342.     ttflush,            /* Flush output routine        */
  343.     scmove,                /* Move cursor routine        */
  344.     sceeol,                /* Erase to end of line routine    */
  345.     sceeop,                /* Erase to end of page routine    */
  346.     sceeop,                /* Clear the desktop        */
  347.     scbeep,                /* Beep! routine        */
  348.     screv,                /* Set reverse video routine    */
  349.     scnothing,            /* Set resolution routine    */
  350. #if COLOR
  351.     scfcol,                /* Set forground color routine    */
  352.     scbcol,                /* Set background color routine    */
  353. #endif /* COLOR */
  354. #if    INSDEL
  355.     scinsline,             /* insert a screen line     */
  356.     scdelline,             /* delete a screen line     */
  357. #endif    /* INSDEL */
  358. };
  359.  
  360. int hpterm;                /* global flag braindead HP-terminal */
  361.  
  362. /** Open terminal device **/
  363. int ttopen()
  364. {
  365.     strcpy(os, "UNIX");
  366. #if BSD
  367.     /* Get tty modes */
  368.     if (ioctl(0, TIOCGETP, &oldsgtty) ||
  369.         ioctl(0, TIOCGETC, &oldtchars) ||
  370.         ioctl(0, TIOCGLTC, &oldlchars))
  371.         return(-1);
  372.  
  373.     /* Save to original mode variables */
  374.     cursgtty = oldsgtty;
  375.  
  376.     /* Set new modes */
  377.     cursgtty.sg_flags |= CBREAK;
  378.     cursgtty.sg_flags &= ~(ECHO|CRMOD);
  379.  
  380.     /* Set tty modes */
  381.     if (ioctl(0, TIOCSETP, &cursgtty) ||
  382.         ioctl(0, TIOCSETC, blank) ||
  383.         ioctl(0, TIOCSLTC, blank))
  384.         return(-1);
  385. #endif /* BSD */
  386. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  387.  
  388. #if SMOS
  389.     /* Extended settings; 890619mhs A3 */
  390.     set_parm(0,-1,-1);
  391. #endif /* SMOS */
  392.  
  393.     /* Get modes */
  394.     if (ioctl(0, TCGETA, &oldterm)) {
  395.         perror("Cannot TCGETA");
  396.         return(-1);
  397.     }
  398.  
  399.     /* Save to original mode variable */
  400.     curterm = oldterm;
  401.  
  402.     /* Set new modes */
  403.     /* I do not believe the flow control settings of the OS should
  404.        be diddled by an application program. But if you do, change this
  405.        1 to a 0, but be warned, all sorts of terminals will get grief
  406.        with this */
  407. #if    1
  408.     curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR);
  409. #else
  410.     curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR|IXON|IXANY|IXOFF);
  411. #endif
  412.     curterm.c_lflag &= ~(ICANON|ISIG|ECHO);
  413.     curterm.c_cc[VMIN] = 1;
  414.     curterm.c_cc[VTIME] = 0;
  415.  
  416. #if SMOS
  417.     /****THIS IS A BIG GUESS ON MY PART... the code changed
  418.       too much between versions for me to be sure this will work - DML */
  419.  
  420.     /* Allow multiple (dual) sessions if already enabled */
  421.     curterm.c_lflag = oldterm.c_lflag & ISIG;
  422.  
  423.     /* Use old SWTCH char if necessary */
  424.     if (curterm.c_lflag != 0)
  425.         curterm.c_cc[VSWTCH] = oldterm.c_cc[VSWTCH];
  426.  
  427.     /* Copy VTI settings    */
  428.     curterm.c_cc[VTBIT] = oldterm.c_cc[VTBIT];
  429.  
  430.     /* Extended settings; 890619mhs A3 */
  431.     set_parm(0,-1,-1);
  432. #endif /* SMOS */
  433.  
  434.     /* Set tty mode */
  435.     if (ioctl(0, TCSETA, &curterm)) {
  436.         perror("Cannot TCSETA");
  437.         return(-1);
  438.     }
  439. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  440. #if AVIION
  441.     /* Get modes */
  442.     if (tcgetattr(0, &oldterm)) {
  443.         perror("Cannot tcgetattr");
  444.         return(-1);
  445.     }
  446.  
  447.     /* Save to original mode variable */
  448.     curterm = oldterm;
  449.  
  450.     /* Set new modes */
  451.     curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR);
  452.     curterm.c_lflag &= ~(ICANON|ISIG|ECHO);
  453.     curterm.c_cc[VMIN] = 1;
  454.     curterm.c_cc[VTIME] = 0;
  455.  
  456. #if AVIION
  457.     /* Set line discipline for Data General */
  458.     curterm.c_line = 0;
  459. #endif /* AVIION */
  460.  
  461.     /* Set tty mode */
  462.     if (tcsetattr(0, TCSANOW, &curterm)) {
  463.         perror("Cannot tcsetattr");
  464.         return(-1);
  465.     }
  466. #endif /* AVIION */
  467.  
  468.     /* Success */
  469.     return(0);
  470. }
  471.  
  472. /** Close terminal device **/
  473. int ttclose()
  474. {
  475.     /* Restore original terminal modes */
  476.     if (reset != (char*)NULL)
  477.         write(1, reset, strlen(reset));
  478.  
  479. #if BSD
  480.     if (ioctl(0, TIOCSETP, &oldsgtty) ||
  481.         ioctl(0, TIOCSETC, &oldtchars) ||
  482.         ioctl(0, TIOCSLTC, &oldlchars))
  483.         return(-1);
  484. #endif /* BSD */
  485.  
  486. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  487. #if SMOS
  488.     /* Extended settings; 890619mhs A3 */
  489.     set_parm(0,-1,-1);
  490. #endif /* SMOS */
  491.     if (ioctl(0, TCSETA, &oldterm))
  492.         return(-1);
  493. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  494.  
  495. #if AVIION
  496.     /* Set tty mode */
  497.     if (tcsetattr(0, TCSANOW, &oldterm))
  498.         return(-1);
  499. #endif /* AVIION */
  500.  
  501.     /* Success */
  502.     return(0);
  503. }
  504.  
  505. /** Flush output buffer to display **/
  506. int ttflush()
  507. {
  508. #if TERMCAP
  509.     int len;
  510.  
  511.     /* Compute length of write */
  512.     len = outbuft - outbuf;
  513.     if (len == 0)
  514.         return(0);
  515.  
  516.     /* Reset buffer position */
  517.     outbuft = outbuf;
  518.  
  519.     /* Perform write to screen */
  520.     return(write(1, outbuf, len) != len);
  521. #else /* TERMCAP */
  522. #if CURSES
  523.     refresh();
  524. #else /* CURSES */
  525.     return(0);
  526. #endif /* CURSES */
  527. #endif /* TERMCAP */
  528. }
  529.  
  530. /** Put character onto display **/
  531. int ttputc(ch)
  532. char ch;                /* Character to display        */
  533. {
  534. #if TERMCAP
  535.     /* Check for buffer full */
  536.     if (outbuft == &outbuf[sizeof(outbuf)])
  537.         ttflush();
  538.  
  539.     /* Add to buffer */
  540.     *outbuft++ = ch;
  541. #endif /* TERMCAP */
  542.  
  543. #if CURSES
  544.     /* Put character on screen */
  545.     addch(ch);
  546. #endif /* CURSES */
  547.  
  548.     return(0);
  549. }
  550.  
  551. /** Add character sequence to keycode entry **/
  552. void addkey(seq, fn)
  553. unsigned char * seq;            /* Character sequence        */
  554. int fn;                    /* Resulting keycode        */
  555. {
  556.     int first;
  557.     struct keyent * cur, * nxtcur;
  558.  
  559.     /* Skip on null sequences */
  560.     if (!seq)
  561.         return;
  562.  
  563.     /* Skip single character sequences */
  564.     if (strlen(seq) < 2)
  565.         return;
  566.  
  567.     /* If no keys defined, go directly to insert mode */
  568.     first = 1;
  569.     if (nxtkey != keymap) {
  570.         
  571.         /* Start at top of key map */
  572.         cur = keymap;
  573.         
  574.         /* Loop until matches exhast */
  575.         while (*seq) {
  576.             
  577.             /* Do we match current character */
  578.             if (*seq == cur->ch) {
  579.                 
  580.                 /* Advance to next level */
  581.                 seq++;
  582.                 cur = cur->nxtlvl;
  583.                 first = 0;
  584.             } else {
  585.                 
  586.                 /* Try next character on same level */
  587.                 nxtcur = cur->samlvl;
  588.                 
  589.                 /* Stop if no more */
  590.                 if (nxtcur)
  591.                     cur = nxtcur;
  592.                 else
  593.                     break;
  594.             }
  595.         }
  596.     }
  597.     
  598.     /* Check for room in keymap */
  599.     if (strlen(seq) > NKEYENT - (nxtkey - keymap))
  600.         return;
  601.         
  602.     /* If first character in sequence is inserted, add to prefix table */
  603.     if (first)
  604.         keyseq[*seq] = 1;
  605.         
  606.     /* If characters are left over, insert them into list */
  607.     for (first = 1; *seq; first = 0) {
  608.         
  609.         /* Make new entry */
  610.         nxtkey->ch = *seq++;
  611.         nxtkey->code = fn;
  612.         
  613.         /* If root, nothing to do */
  614.         if (nxtkey != keymap) {
  615.             
  616.             /* Set first to samlvl, others to nxtlvl */
  617.             if (first)
  618.                 cur->samlvl = nxtkey;
  619.             else
  620.                 cur->nxtlvl = nxtkey;
  621.         }
  622.  
  623.         /* Advance to next key */
  624.         cur = nxtkey++;
  625.     }
  626. }
  627.  
  628. /** Grab input characters, with wait **/
  629. unsigned char grabwait()
  630. {
  631. #if BSD
  632.     unsigned char ch;
  633.  
  634.     /* Perform read */
  635.     if (read(0, &ch, 1) != 1) {
  636.         puts("** Horrible read error occured **");
  637.         exit(1);
  638.     }
  639.     return(ch);
  640. #endif /* BSD */
  641. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || AVIION
  642.     unsigned char ch;
  643.  
  644.     /* Change mode, if necessary */
  645.     if (curterm.c_cc[VTIME]) {
  646.         curterm.c_cc[VMIN] = 1;
  647.         curterm.c_cc[VTIME] = 0;
  648. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  649.         ioctl(0, TCSETA, &curterm);
  650. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  651. #if AVIION
  652.         tcsetattr(0, TCSANOW, &curterm);
  653. #endif /* AVIION */        
  654.     }
  655.  
  656.     /* Perform read */
  657.     if (read(0, &ch, 1) != 1) {
  658.         puts("** Horrible read error occured **");
  659.         exit(1);
  660.     }
  661.  
  662.     /* Return new character */
  663.     return(ch);
  664. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || AVIION */
  665. }
  666.  
  667. /** Grab input characters, short wait **/
  668. unsigned char grabnowait()
  669. {
  670. #if BSD
  671.     static struct timeval timout = { 0, 500000L };
  672.     int count, r;
  673.  
  674.     /* Select input */
  675.     r = 1;
  676.     count = select(1, &r, NULL, NULL, &timout);
  677.     if (count == 0)
  678.         return(TIMEOUT);
  679.     if (count < 0) {
  680.         puts("** Horrible select error occured **");
  681.         exit(1);
  682.     }
  683.  
  684.     /* Perform read */
  685.     return(grabwait());
  686. #endif /* BSD */
  687. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || AVIION
  688.     int count;
  689.     unsigned char ch;
  690.  
  691.     /* Change mode, if necessary */
  692.     if (curterm.c_cc[VTIME] == 0) {
  693.         curterm.c_cc[VMIN] = 0;
  694.         curterm.c_cc[VTIME] = 5;
  695. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  696.         ioctl(0, TCSETA, &curterm);
  697. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  698. #if AVIION
  699.         tcsetattr(0, TCSANOW, &curterm);
  700. #endif /* AVIION */        
  701.     }
  702.  
  703.     /* Perform read */
  704.     count = read(0, &ch, 1);
  705.     if (count < 0) {
  706.         puts("** Horrible read error occured **");
  707.         exit(1);
  708.     }
  709.     if (count == 0)
  710.         return(TIMEOUT);
  711.  
  712.     /* Return new character */
  713.     return(ch);
  714. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || AVIION */
  715. }
  716.  
  717. /** Queue input character **/
  718. void qin(ch)
  719. int ch;                    /* Character to add        */
  720. {
  721.     /* Check for overflow */
  722.     if (inbuft == &inbuf[sizeof(inbuf)]) {
  723.         
  724.         /* Annoy user */
  725.         scbeep();
  726.         return;
  727.     }
  728.     
  729.     /* Add character */
  730.     *inbuft++ = ch;
  731. }
  732.  
  733. /** Cook input characters **/
  734. void cook()
  735. {
  736.     unsigned char ch;
  737.     struct keyent * cur;
  738.     
  739.     /* Get first character untimed */
  740.     ch = grabwait();
  741.     qin(ch);
  742.     
  743.     /* Skip if the key isn't a special leading escape sequence */
  744.     if (keyseq[ch] == 0) {
  745.         /* if it is a null, make it a (0/1/32) */
  746.         if (ch == 0) {
  747.             qin(CTRL >> 8);    /* control */
  748.             qin(32);    /* space */
  749.         }
  750.         return;
  751.     }
  752.  
  753.     /* Start at root of keymap */
  754.     cur = keymap;
  755.  
  756.     /* Loop until keymap exhasts */
  757.     while (cur) {
  758.  
  759.         /* Did we find a matching character */
  760.         if (cur->ch == ch) {
  761.  
  762.             /* Is this the end */
  763.             if (cur->nxtlvl == NULL) {
  764.  
  765.                 /* Replace all character with new sequence */
  766.                 inbuft = inbuf;
  767.                 qin(cur->code);
  768.                 return;
  769.             } else {
  770.                 /* Advance to next level */
  771.                 cur = cur->nxtlvl;
  772.             
  773.                 /* Get next character, timed */
  774.                 ch = grabnowait();
  775.                 if (ch == TIMEOUT)
  776.                     return;
  777.  
  778.                 /* Queue character */
  779.                 qin(ch);
  780.             }
  781.         } else
  782.             /* Try next character on same level */
  783.             cur = cur->samlvl;
  784.     }
  785. }
  786.  
  787. /** Return cooked characters **/
  788. int ttgetc()
  789. {
  790.     int ch;
  791.  
  792.     /* Loop until character is in input buffer */
  793.     while (inbufh == inbuft)
  794.         cook();
  795.     
  796.     /* Get input from buffer, now that it is available */
  797.     ch = *inbufh++;
  798.  
  799.     /* reset us to the beginning of the buffer if there are no more
  800.        pending characters */
  801.     if (inbufh == inbuft)
  802.         inbufh = inbuft = inbuf;
  803.     
  804.     /* Return next character */
  805.     return(ch);
  806. }
  807.  
  808. #if TYPEAH
  809. int typahead()
  810. {
  811.     int count;
  812.  
  813.     /* See if internal buffer is non-empty */
  814.     if (inbufh != inbuft)
  815.         return(1);
  816.  
  817.     /* Now check with system */
  818. #ifdef FIONREAD  /* Watch out!  This could bite you! */
  819.     /* Get number of pending characters */
  820.     if (ioctl(0, FIONREAD, &count))
  821.         return(0);
  822.     return(count);
  823. #else /* not FIONREAD */
  824. #ifdef VAT
  825.     return(0);
  826. #else /* not VAT */
  827.     /* Ask hardware for count */
  828.     count = ioctl(0, FIORDCHK, 0);
  829.     if (count < 0)
  830.         return(0);
  831.     return(count);
  832. #endif    /* VAT */
  833. #endif /* FIONREAD */
  834. }
  835. #endif /* TYPEAH */
  836.  
  837. #if TERMCAP
  838. /** Put out sequence, with padding **/
  839. void putpad(seq)
  840. char * seq;                /* Character sequence        */
  841. {
  842.     /* Check for null */
  843.     if (!seq)
  844.         return;
  845.  
  846.     /* Call on termcap to send sequence */
  847.     tputs(seq, 1, ttputc);
  848. }
  849. #endif /* TERMCAP */
  850.  
  851. /** Initialize screen package **/
  852. int scopen()
  853. {
  854. #if TERMCAP
  855.     char * cp, tcbuf[1024];
  856.     int status;
  857.     struct capbind * cb;
  858.     struct keybind * kp;
  859.     char err_str[NSTRING];
  860.  
  861.     char * getenv(), * tgetstr();
  862.  
  863. #ifndef VAT
  864. #define TGETSTR(a,b)    tgetstr((a), (b))
  865. #else
  866. #define TGETSTR(a,b)    tgetstr((a), *(b))
  867. #endif
  868.  
  869. #if HPUX8 || HPUX9 || VAT || AUX
  870.     /* HP-UX and AUX doesn't seem to have these in the termcap library */
  871.     char PC, * UP;
  872.     short ospeed;
  873. #else /* not HPUX8 || HPUX9 || VAT || AUX */
  874.     extern char PC, * UP;
  875.     extern short ospeed;
  876. #endif /* HPUX8 || HPUX9 || VAT || AUX */
  877.  
  878.     /* Get terminal type */
  879.     cp = getenv("TERM");
  880.     if (!cp) {
  881.         puts(TEXT182);
  882. /*        "Environment variable \"TERM\" not define!" */
  883.         exit(1);
  884.     }
  885.  
  886.     /* Try to load termcap */
  887.     status = tgetent(tcbuf, cp);
  888.     if (status == -1) {
  889.         puts("Cannot open termcap file");
  890.         exit(1);
  891.     }
  892.     if (status == 0) {
  893.         sprintf(err_str, TEXT183, cp);
  894. /*        "No entry for terminal type \"%s\"\n" */
  895.         puts(err_str);
  896.         exit(1);
  897.     }
  898.  
  899.     /* Get size from termcap */
  900.     term.t_nrow = tgetnum("li") - 1;
  901.     term.t_ncol = tgetnum("co");
  902.     if (term.t_nrow < 3 || term.t_ncol < 3) {
  903.         puts("Screen size is too small!");
  904.         exit(1);
  905.     }
  906.  
  907.     /* initialize max number of rows and cols     */
  908.     term.t_mrow = term.t_nrow;
  909.     term.t_mcol = term.t_ncol;
  910.  
  911.     /* Start grabbing termcap commands */
  912.     cp = tcapbuf;
  913.  
  914.     /* Get the reset string */
  915.     reset = TGETSTR("is", &cp);
  916.  
  917.     /* Get the pad character */
  918.     if (tgetstr("pc", &cp))
  919.         PC = tcapbuf[0];
  920.  
  921.     /* Get up line capability */
  922.     UP = TGETSTR("up", &cp);
  923.  
  924.     /* Get other capabilities */
  925.     cb = capbind;
  926.     while (cb < &capbind[sizeof(capbind)/sizeof(*capbind)]) {
  927.         cb->store = TGETSTR(cb->name, &cp);
  928.         cb++;
  929.     }
  930.  
  931.     /* Check for minimum */
  932.     if (!capbind[CAP_CL].store && (!capbind[CAP_CM].store || !UP)) {
  933.         puts("This terminal doesn't have enough power to run microEmacs!");
  934.         exit(1);
  935.     }
  936.  
  937.     /* Set reverse video and erase to end of line */
  938.     if (capbind[CAP_SO].store && capbind[CAP_SE].store)
  939.         revexist = TRUE;
  940.     if (!capbind[CAP_CE].store)
  941.         eolexist = FALSE;
  942.  
  943.     /* Get keybindings */
  944.     kp = keybind;
  945.     while (kp < &keybind[sizeof(keybind)/sizeof(*keybind)]) {
  946.         addkey(TGETSTR(kp->name, &cp), kp->value);
  947.         kp++;
  948.     }
  949.  
  950.     /* check for HP-Terminal (so we can label its function keys) */
  951.     hpterm = tgetflag("xs");
  952.  
  953.     /* Open terminal device */
  954.     if (ttopen()) {
  955.         puts("Cannot open terminal");
  956.         exit(1);
  957.     }
  958.  
  959.     /* Set speed for padding sequences */
  960. #if BSD
  961.     ospeed = cursgtty.sg_ospeed;
  962. #endif /* BSD */
  963. #if USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
  964.     ospeed = curterm.c_cflag & CBAUD;
  965. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
  966. #if AVIION
  967.     ospeed = cfgetospeed(&curterm);
  968. #endif /* AVIION */
  969.     
  970.     /* Send out initialization sequences */
  971.     putpad(capbind[CAP_IS].store);
  972.     putpad(capbind[CAP_KS].store);
  973.     sckopen();
  974. #endif /* TERMCAP */
  975.  
  976. #if CURSES
  977.     /* Initialize screen */
  978.     initscr();
  979.  
  980.     /* Set size of screen */
  981.     term.t_nrow = LINES - 1;
  982.     term.t_ncol = COLS;
  983.  
  984.     /* Open terminal device */
  985.     if (ttopen()) {
  986.         puts("Cannot open terminal");
  987.         exit(1);
  988.     }
  989. #endif /* CURSES */
  990.  
  991.     /* Success */
  992.     return(0);
  993. }
  994.  
  995. /** Close screen package **/
  996. int scclose()
  997. {
  998. #if TERMCAP
  999.     /* Turn off keypad mode */
  1000.     putpad(capbind[CAP_KE].store);
  1001.     sckclose();
  1002.  
  1003.     /* Close terminal device */
  1004.     ttflush();
  1005.     ttclose();
  1006. #endif /* TERMCAP */
  1007.  
  1008. #if CURSES
  1009.     /* Turn off curses */
  1010.     endwin();
  1011.  
  1012.     /* Close terminal device */
  1013.     ttflush();
  1014.     ttclose();
  1015. #endif /* CURSES */
  1016.  
  1017.     /* Success */
  1018.     return(0);
  1019. }
  1020.  
  1021. /* open keyboard -hm */
  1022. int sckopen()
  1023. {
  1024. #if TERMCAP
  1025.     putpad(capbind[CAP_KS].store);
  1026.     ttflush();
  1027. #if    FLABEL
  1028.     dis_ufk();
  1029. #endif
  1030. #endif
  1031. }
  1032.  
  1033. /* close keyboard -hm */
  1034. int sckclose()
  1035. {
  1036. #if TERMCAP
  1037.     putpad(capbind[CAP_KE].store);
  1038.     ttflush();
  1039. #if    FLABEL
  1040.     dis_sfk();
  1041. #endif
  1042. #endif
  1043. }
  1044.  
  1045. /** Move cursor **/
  1046. int scmove(row, col)
  1047. int row;                /* Row number            */
  1048. int col;                /* Column number        */
  1049. {
  1050.     char *tgoto();
  1051.  
  1052. #if TERMCAP
  1053.     /* Call on termcap to create move sequence */
  1054.     putpad(tgoto(capbind[CAP_CM].store, col, row));
  1055. #endif /* TERMCAP */
  1056.  
  1057. #if CURSES
  1058.     move(row, col);
  1059. #endif /* CURSES */
  1060.  
  1061.     /* Success */
  1062.     return(0);
  1063. }
  1064.  
  1065. /** Erase to end of line **/
  1066. int sceeol()
  1067. {
  1068. #if TERMCAP
  1069.     /* Send erase sequence */
  1070.     putpad(capbind[CAP_CE].store);
  1071. #endif /* TERMCAP */
  1072.  
  1073. #if CURSES
  1074.     clrtoeol();
  1075. #endif /* CURSES */
  1076.  
  1077.     /* Success */
  1078.     return(0);
  1079. }
  1080.  
  1081. /** Clear screen **/
  1082. int sceeop()
  1083. {
  1084. #if TERMCAP
  1085. #if COLOR
  1086.     scfcol(gfcolor);
  1087.     scbcol(gbcolor);
  1088. #endif /* COLOR */
  1089.     /* Send clear sequence */
  1090.     putpad(capbind[CAP_CL].store);
  1091. #endif /* TERMCAP */
  1092.  
  1093. #if CURSES
  1094.     erase();
  1095. #endif /* CURSES */
  1096.  
  1097.  
  1098.     /* Success */
  1099.     return(0);
  1100. }
  1101.  
  1102. /** Set reverse video state **/
  1103. int screv(state)
  1104. int state;                /* New state            */
  1105. {
  1106. #if TERMCAP
  1107. #if COLOR
  1108.     int ftmp, btmp;        /* temporaries for colors */
  1109. #endif /* COLOR */
  1110.  
  1111.     /* Set reverse video state */
  1112.     putpad(state ? capbind[CAP_SO].store : capbind[CAP_SE].store);
  1113.  
  1114. #if COLOR
  1115.     if (state == FALSE) {
  1116.         ftmp = cfcolor;
  1117.         btmp = cbcolor;
  1118.         cfcolor = -1;
  1119.         cbcolor = -1;
  1120.         scfcol(ftmp);
  1121.         scbcol(btmp);
  1122.     }
  1123. #endif /* COLOR */
  1124. #endif /* TERMCAP */
  1125.  
  1126. #if CURSES
  1127.     if (state)
  1128.         standout();
  1129.     else
  1130.         standend();
  1131. #endif /* CURSES */
  1132.  
  1133.     /* Success */
  1134.     return(0);
  1135. }
  1136.  
  1137. /** Beep **/
  1138. scbeep()
  1139. {
  1140. #if TERMCAP
  1141. #if !NOISY
  1142.     /* Send out visible bell, if it exists */
  1143.     if (capbind[CAP_VB].store)
  1144.         putpad(capbind[CAP_VB].store);
  1145.     else
  1146. #endif /* not NOISY */
  1147.         /* The old standby method */
  1148.         ttputc('\7');
  1149. #endif /* TERMCAP */
  1150.  
  1151. #if CURSES
  1152.     addch('\7');        /* FIX THIS! beep() and flash comes up undefined */
  1153. #endif /* CURSES */
  1154.  
  1155.     /* Success */
  1156.     return(0);
  1157. }
  1158.  
  1159. #if COLOR
  1160. static char cmap[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
  1161.  
  1162. /** Set foreground color **/
  1163. int scfcol(color)
  1164. int color;        /* Color to set            */
  1165. {
  1166. #if TERMCAP
  1167.     /* Skip if already the correct color */
  1168.     if (color == cfcolor)
  1169.         return(0);
  1170.  
  1171.     /* Send out color sequence */
  1172.     if (capbind[CAP_C0].store) {
  1173.         putpad(capbind[CAP_C0 + (color & 7)].store);
  1174.         cfcolor = color;
  1175.     }
  1176. #if USG || AUX
  1177.     else if (capbind[CAP_SF].store) {
  1178.         putpad(tparm(capbind[CAP_SF].store, cmap[color & 7]));
  1179.         cfcolor = color;
  1180.     }
  1181. #endif /* USG || AUX */
  1182. #endif /* TERMCAP */
  1183.  
  1184. #if CURSES
  1185.     /* ? */
  1186. #endif /* CURSES */
  1187.     return(0);
  1188. }
  1189.  
  1190. /** Set background color **/
  1191. int scbcol(color)
  1192. int color;            /* Color to set            */
  1193. {
  1194. #if TERMCAP
  1195.     /* Skip if already the correct color */
  1196.     if (color == cbcolor)
  1197.         return(0);
  1198.  
  1199.     /* Send out color sequence */
  1200.     if (capbind[CAP_C0].store) {
  1201.         putpad(capbind[CAP_D0 + (color & 7)].store);
  1202.         cbcolor = color;
  1203.     }
  1204. #if USG || AUX
  1205.     else if (capbind[CAP_SB].store) {
  1206.         putpad(tparm(capbind[CAP_SB].store, cmap[color & 7]));
  1207.         cbcolor = color;
  1208.     }
  1209. #endif /* USG || AUX */
  1210. #endif /* TERMCAP */
  1211.  
  1212. #if CURSES
  1213.     /* ? */
  1214. #endif /* CURSES */
  1215.     return(0);
  1216. }
  1217. #endif /* COLOR */
  1218.  
  1219. /** Set palette **/
  1220. int spal(cmd)
  1221. char * cmd;                /* Palette command        */
  1222. {
  1223.     int code, dokeymap;
  1224.     char * cp;
  1225.  
  1226.     /* Check for keymapping command */
  1227.     if (strncmp(cmd, "KEYMAP ", 7) == 0)
  1228.         dokeymap = 1;
  1229.     else
  1230. #if TERMCAP
  1231. #if COLOR
  1232.     if (strncmp(cmd, "CLRMAP ", 7) == 0)
  1233.         dokeymap = 0;
  1234.     else
  1235. #endif /* COLOR */
  1236. #endif /* TERMCAP */
  1237.         return(0);
  1238.     cmd += 7;
  1239.  
  1240.     /* Look for space */
  1241.     for (cp = cmd; *cp != '\0'; cp++)
  1242.         if (*cp == ' ') {
  1243.             *cp++ = '\0';
  1244.             break;
  1245.         }
  1246.     if (*cp == '\0')
  1247.         return(1);
  1248.  
  1249.     /* Perform operation */
  1250.     if (dokeymap) {
  1251.  
  1252.         /* Convert to keycode */
  1253.         code = stock(cmd);
  1254.  
  1255.         /* Add to tree */
  1256.         addkey(cp, code);
  1257.     }
  1258. #if TERMCAP
  1259. #if COLOR
  1260.     else {
  1261.  
  1262.         /* Convert to color number */
  1263.         code = atoi(cmd);
  1264.         if (code < 0 || code > 15)
  1265.             return(1);
  1266.  
  1267.         /* Move color code to capability structure */
  1268.         capbind[CAP_C0 + code].store = malloc(strlen(cp) + 1);
  1269.         if (capbind[CAP_C0 + code].store)
  1270.             strcpy(capbind[CAP_C0 + code].store, cp);
  1271.     }
  1272. #endif /* COLOR */
  1273. #endif /* TERMCAP */
  1274.     return(0);
  1275. }
  1276.  
  1277. #if BSD || SUN || HPUX8 || HPUX9 || AVIION
  1278. /* Surely more than just BSD systems do this */
  1279.  
  1280. /** Perform a stop signal **/
  1281. int bktoshell(f, n)
  1282. {
  1283.     /* Reset the terminal and go to the last line */
  1284.     vttidy();
  1285.     
  1286.     /* Okay, stop... */
  1287.     kill(getpid(), SIGTSTP);
  1288.  
  1289.     /* We should now be back here after resuming */
  1290.  
  1291.     /* Reopen the screen and redraw */
  1292.     scopen();
  1293.     curwp->w_flag = WFHARD;
  1294.     sgarbf = TRUE;
  1295.  
  1296.     /* Success */
  1297.     return(0);
  1298. }
  1299.  
  1300. #endif /* BSD || SUN || HPUX8 || HPUX9 || AVIION */
  1301.  
  1302. /** Get time of day **/
  1303. char * timeset()
  1304. {
  1305.     long int buf; /* Should be time_t */
  1306.     char * sp, * cp;
  1307.  
  1308.     char * ctime();
  1309.  
  1310.     /* Get system time */
  1311.     time(&buf);
  1312.  
  1313.     /* Pass system time to converter */
  1314.     sp = ctime(&buf);
  1315.  
  1316.     /* Eat newline character */
  1317.     for (cp = sp; *cp; cp++)
  1318.         if (*cp == '\n') {
  1319.             *cp = '\0';
  1320.             break;
  1321.         }
  1322.     return(sp);
  1323. }
  1324.  
  1325. #if USG || AUX || SMOS || HPUX8 || XENIX
  1326. /** Rename a file **/
  1327. int rename(file1, file2)
  1328. char * file1;                /* Old file name        */
  1329. char * file2;                /* New file name        */
  1330. {
  1331.     struct stat buf1;
  1332.     struct stat buf2;
  1333.  
  1334.     /* No good if source file doesn't exist */
  1335.     if (stat(file1, &buf1))
  1336.         return(-1);
  1337.  
  1338.     /* Check for target */
  1339.     if (stat(file2, &buf2) == 0) {
  1340.  
  1341.         /* See if file is the same */
  1342.         if (buf1.st_dev == buf2.st_dev &&
  1343.             buf1.st_ino == buf2.st_ino)
  1344.  
  1345.             /* Not necessary to rename file */
  1346.             return(0);
  1347.     }
  1348.  
  1349.     /* Get rid of target */
  1350.     unlink(file2);
  1351.  
  1352.     /* Link two files together */
  1353.     if (link(file1, file2))
  1354.         return(-1);
  1355.  
  1356.     /* Unlink original file */
  1357.     return(unlink(file1));
  1358. }
  1359. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || XENIX */
  1360.  
  1361. /** Callout to system to perform command **/
  1362. int callout(cmd)
  1363. char * cmd;                /* Command to execute        */
  1364. {
  1365.     int status;
  1366.  
  1367.     /* Close down */
  1368.     scmove(term.t_nrow, 0);
  1369.     ttflush();
  1370.     sckclose();
  1371.     ttclose();
  1372.  
  1373.     /* Do command */
  1374.     status = system(cmd) == 0;
  1375.  
  1376.     /* Restart system */
  1377.         sgarbf = TRUE;
  1378.     sckopen();
  1379.     if (ttopen()) {
  1380.         puts("** Error reopening terminal device **");
  1381.         exit(1);
  1382.     }
  1383.  
  1384.     /* Success */
  1385.         return(status);
  1386. }
  1387.  
  1388. /** Create subshell **/
  1389. int spawncli(f, n)
  1390. int f;                    /* Flags            */
  1391. int n;                    /* Argument count        */
  1392. {
  1393.     char * sh;
  1394.  
  1395.     char * getenv();
  1396.  
  1397.     /* Don't allow this command if restricted */
  1398.     if (restflag)
  1399.         return(resterr());
  1400.  
  1401.     /* Get shell path */
  1402.     sh = getenv("SHELL");
  1403.     if (!sh)
  1404. #if BSD || SUN
  1405.         sh = "/bin/csh";
  1406. #endif /* BSD || SUN */
  1407. #if USG || AUX || SMOS || HPUX8 || HPUX9 || XENIX || AVIION
  1408.         sh = "/bin/sh";
  1409. #endif /* USG || AUX || SMOS || HPUX8 || HPUX9 || XENIX || AVIION */
  1410.  
  1411.     /* Do shell */
  1412.     return(callout(sh));
  1413. }
  1414.  
  1415. /** Spawn a command **/
  1416. int spawn(f, n)
  1417. int f;                    /* Flags            */
  1418. int n;                    /* Argument count        */
  1419. {
  1420.     char line[NLINE];
  1421.     int s;
  1422.  
  1423.     /* Don't allow this command if restricted */
  1424.     if (restflag)
  1425.         return(resterr());
  1426.  
  1427.     /* Get command line */
  1428.     s = mlreply("!", line, NLINE);
  1429.     if (!s)
  1430.         return(s);
  1431.  
  1432.     /* Perform the command */
  1433.     s = callout(line);
  1434.  
  1435.     /* if we are interactive, pause here */
  1436.     if (clexec == FALSE) {
  1437.             mlwrite("[End]");
  1438.         ttflush();
  1439.         ttgetc();
  1440.         }
  1441.         return(s);
  1442. }
  1443.  
  1444. /** Execute program **/
  1445. int execprg(f, n)
  1446. int f;                    /* Flags            */
  1447. int n;                    /* Argument count        */
  1448. {
  1449.     /* Same as spawn */
  1450.     return(spawn(f, n));
  1451. }
  1452.  
  1453. /** Pipe output of program to buffer **/
  1454. int pipecmd(f, n)
  1455. int f;                    /* Flags            */
  1456. int n;                    /* Argument count        */
  1457. {
  1458.     char line[NLINE];
  1459.     int s;
  1460.     BUFFER * bp;
  1461.     WINDOW * wp;
  1462.     static char filnam[] = "command";
  1463.  
  1464.     /* Don't allow this command if restricted */
  1465.     if (restflag)
  1466.         return(resterr());
  1467.  
  1468.     /* Get pipe-in command */
  1469.     s = mlreply("@", line, NLINE);
  1470.     if (!s)
  1471.         return(s);
  1472.  
  1473.     /* Get rid of the command output buffer if it exists */
  1474.     bp = bfind(filnam, FALSE, 0);
  1475.     if (bp) {
  1476.         /* Try to make sure we are off screen */
  1477.         wp = wheadp;
  1478.         while (wp) {
  1479.             if (wp->w_bufp == bp) {
  1480.                 onlywind(FALSE, 1);
  1481.                 break;
  1482.             }
  1483.             wp = wp->w_wndp;
  1484.         }
  1485.         if (!zotbuf(bp))
  1486.             return(0);
  1487.     }
  1488.  
  1489.     /* Add output specification */
  1490.     strcat(line, ">");
  1491.     strcat(line, filnam);
  1492.  
  1493.     /* Do command */
  1494.     s = callout(line);
  1495.     if (!s)
  1496.         return(s);
  1497.  
  1498.     /* Split the current window to make room for the command output */
  1499.     if (!splitwind(FALSE, 1))
  1500.         return(0);
  1501.  
  1502.     /* ...and read the stuff in */
  1503.     if (!getfile(filnam, FALSE))
  1504.         return(0);
  1505.  
  1506.     /* Make this window in VIEW mode, update all mode lines */
  1507.     curwp->w_bufp->b_mode |= MDVIEW;
  1508.     wp = wheadp;
  1509.     while (wp) {
  1510.         wp->w_flag |= WFMODE;
  1511.         wp = wp->w_wndp;
  1512.     }
  1513.  
  1514.     /* ...and get rid of the temporary file */
  1515.     unlink(filnam);
  1516.     return(1);
  1517. }
  1518.  
  1519. /** Filter buffer through command **/
  1520. int filter(f, n)
  1521. int f;                    /* Flags            */
  1522. int n;                    /* Argument count        */
  1523. {
  1524.     char line[NLINE], tmpnam[NFILEN];
  1525.     int s;
  1526.     BUFFER * bp;
  1527.     static char bname1[] = "fltinp";
  1528.     static char filnam1[] = "fltinp";
  1529.     static char filnam2[] = "fltout";
  1530.  
  1531.     /* Don't allow this command if restricted */
  1532.     if (restflag)
  1533.         return(resterr());
  1534.  
  1535.     /* Don't allow filtering of VIEW mode buffer */
  1536.     if (curbp->b_mode & MDVIEW)
  1537.         return(rdonly());
  1538.  
  1539.     /* Get the filter name and its args */
  1540.     s = mlreply("#", line, NLINE);
  1541.     if (!s)
  1542.         return(s);
  1543.  
  1544.     /* Setup the proper file names */
  1545.     bp = curbp;
  1546.     strcpy(tmpnam, bp->b_fname);    /* Save the original name */
  1547.     strcpy(bp->b_fname, bname1);    /* Set it to our new one */
  1548.  
  1549.     /* Write it out, checking for errors */
  1550.     if (!writeout(filnam1, "w")) {
  1551.         mlwrite("[Cannot write filter file]");
  1552.         strcpy(bp->b_fname, tmpnam);
  1553.         return(0);
  1554.     }
  1555.  
  1556.     /* Setup input and output */
  1557.     strcat(line," <fltinp >fltout");
  1558.  
  1559.     /* Perform command */
  1560.     s = callout(line);
  1561.  
  1562.     /* If successful, read in file */
  1563.     if (s) {
  1564.         s = readin(filnam2, FALSE);
  1565.         if (s)
  1566.             /* Mark buffer as changed */
  1567.             bp->b_flag |= BFCHG;
  1568.     }
  1569.             
  1570.  
  1571.     /* Reset file name */
  1572.     strcpy(bp->b_fname, tmpnam);
  1573.  
  1574.     /* and get rid of the temporary file */
  1575.     unlink(filnam1);
  1576.     unlink(filnam2);
  1577.  
  1578.     /* Show status */
  1579.     if (!s)
  1580.         mlwrite("[Execution failed]");
  1581.     return(s);
  1582. }
  1583.  
  1584. /** Get first filename from pattern **/
  1585. char *getffile(fspec)
  1586. char *fspec;                /* Filename specification    */
  1587. {
  1588.     int index, point, extflag;
  1589.  
  1590.     /* First parse the file path off the file spec */
  1591.     strcpy(path, fspec);
  1592.     index = strlen(path) - 1;
  1593.     while (index >= 0 && (path[index] != '/' &&
  1594.         path[index] != '\\' && path[index] != ':'))
  1595.         --index;
  1596.     path[index+1] = '\0';
  1597.  
  1598.  
  1599.     /* Check for an extension */
  1600.     point = strlen(fspec) - 1;
  1601.     extflag = FALSE;
  1602.     while (point >= 0) {
  1603.         if (fspec[point] == '.') {
  1604.             extflag = TRUE;
  1605.             break;
  1606.         }
  1607.         point--;
  1608.     }
  1609.  
  1610.     /* Open the directory pointer */
  1611.     if (dirptr) {
  1612.         closedir(dirptr);
  1613.         dirptr = NULL;
  1614.     }
  1615.  
  1616.     dirptr = opendir((path[0] == '\0') ? "./" : path);
  1617.  
  1618.     if (!dirptr)
  1619.         return(NULL);
  1620.  
  1621.     strcpy(rbuf, path);
  1622.     nameptr = &rbuf[strlen(rbuf)];
  1623.  
  1624.     /* ...and call for the first file */
  1625.     return(getnfile());
  1626. }
  1627.  
  1628. /** Get next filename from pattern **/
  1629. char *getnfile()
  1630. {
  1631.     int index;
  1632.     struct DIRENTRY * dp;
  1633.     struct stat fstat;
  1634.  
  1635.     /* ...and call for the next file */
  1636.     do {
  1637.         dp = readdir(dirptr);
  1638.         if (!dp)
  1639.             return(NULL);
  1640.  
  1641.         /* Check to make sure we skip all weird entries except directories */
  1642.         strcpy(nameptr, dp->d_name);
  1643.  
  1644.     } while (stat(rbuf, &fstat) ||
  1645.         ((fstat.st_mode & S_IFMT) & (S_IFREG | S_IFDIR)) == 0);
  1646.  
  1647.     /* if this entry is a directory name, say so */
  1648.     if ((fstat.st_mode & S_IFMT) == S_IFDIR)
  1649.         strcat(rbuf, DIRSEPSTR);
  1650.  
  1651.     /* Return the next file name! */
  1652.     return(rbuf);
  1653. }
  1654.  
  1655. #if FLABEL
  1656. /*---------------------------------------------------------------------------*
  1657.  
  1658.       handle the function keys and function key labels on HP-Terminals
  1659.       -----------------------------------------------------------------
  1660.  
  1661.       Hellmuth Michaelis    e-mail: hm@hcshh.hcs.de
  1662.  
  1663.  *---------------------------------------------------------------------------*/
  1664.  
  1665. static unsigned char flabstor[8][50];        /* label & xmit backup store */
  1666. static char flabstof[8] = {0,0,0,0,0,0,0,0};    /* filled flag */
  1667.  
  1668. int fnclabel(f, n)        /* label a function key */
  1669.  
  1670. int f;        /* Default argument */
  1671. int n;        /* function key number 1...8 on hp-terminals */
  1672.  
  1673. {
  1674.     char lbl[20];    /* label string buffer */
  1675.     char xmit[5];    /* transmitted string ( ESC 'p'...'w' ) */
  1676.     char buf[80];    /* writeout buffer */
  1677.     int i;        /* general purpose index */
  1678.     int status;    /* return status */
  1679.  
  1680.     /* check if we are connected to an hp-terminal */
  1681.     if (!hpterm)
  1682.         return(FALSE);
  1683.  
  1684.     /* must be called with an argument */
  1685.     if (f == FALSE) {
  1686.         mlwrite(TEXT246);
  1687. /*            "%%Need function key number"*/
  1688.         return(FALSE);
  1689.     }
  1690.  
  1691.     /* and it must be a legal key number */
  1692.     if (n < 1 || n > 8) {
  1693.         mlwrite(TEXT247);
  1694. /*            "%%Function key number out of range"*/
  1695.         return(FALSE);
  1696.     }
  1697.  
  1698.     /* get the string to send */
  1699.     lbl[0] = '\0';    /* we don't now the label yet */
  1700.  
  1701.     if ((status = mlreply(TEXT248, lbl, 19)) != TRUE)
  1702. /*                  "Enter Label String: "*/
  1703.         return(status);
  1704.  
  1705.     lbl[16] = '\0';
  1706.      i = strlen(lbl);
  1707.  
  1708.     /* set up escape sequence to send to terminal */
  1709.     xmit[0] = 0x1b;
  1710.     xmit[1] = 'o' + n;
  1711.     xmit[2] = '\0';
  1712.  
  1713.     sprintf(flabstor[n-1], "%c&f0a%dk%dd2L%s%s", (char)0x1b, n, i,
  1714.                     lbl, xmit);
  1715.     write(1, flabstor[n-1], strlen(flabstor[n-1]));
  1716.     flabstof[n-1] = 1;
  1717.  
  1718.     sprintf(buf, "%c&jB", (char)0x1b);
  1719.     write(1, buf, strlen(buf));
  1720.  
  1721.     return(TRUE);
  1722. }
  1723.  
  1724. /* display user function key labels */
  1725. static void dis_ufk()
  1726.  
  1727. {
  1728.     int label_num;
  1729.     char buf[6];
  1730.  
  1731.     if (!hpterm)
  1732.         return;
  1733.  
  1734.     for (label_num = 0; label_num < 8; label_num++)
  1735.         if (flabstof[label_num])
  1736.             write(1, flabstor[label_num],
  1737.                 strlen(flabstor[label_num]));
  1738.     sprintf(buf, "%c&jB", (char)0x1b);
  1739.     write(1, buf, strlen(buf));
  1740. }
  1741.  
  1742. /* display system function key labels */
  1743. static void dis_sfk()
  1744.  
  1745. {
  1746.     char buf[6];
  1747.  
  1748.     if (!hpterm)
  1749.         return;
  1750.     sprintf(buf, "%c&jA", (char)0x1b);
  1751.     write(1, buf, strlen(buf));
  1752. }
  1753. #endif /* FLABEL */
  1754.  
  1755. #if XENIX && FILOCK
  1756. int mkdir(name, mode)
  1757. char *name;    /* name of directory to create */
  1758. int mode;    /* umask for creation (which we blissfully ignore...) */
  1759. {
  1760.     char buf[80];
  1761.  
  1762.     strcpy(buf, "mkdir ");
  1763.     strcat(buf, name);
  1764.     strcat(buf, " > /dev/null 2>&1");
  1765.     return(system(buf));
  1766. }
  1767.  
  1768. int rmdir(name)
  1769. char *name;    /* name of directory to delete */
  1770. {
  1771.     char buf[80];
  1772.  
  1773.     strcpy(buf,"rmdir ");
  1774.     strcat(buf, name);
  1775.     strcat(buf, " > /dev/null 2>&1");
  1776.     return(system(buf));
  1777. }
  1778. #endif /* XENIX & FILOCK */
  1779.  
  1780. #endif /* BSD || USG || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || AVIION */
  1781.